package com.tianji.learning.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Duration;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Data
@AllArgsConstructor(staticName = "of")
@NoArgsConstructor
public class DelayTask<D> implements Delayed {
    private Long deadLineNanos;  //延时执行时间的纳秒值
    private D date; //延时任务的数据（可携带的数据）

    //有参构造，创建一个延时任务duration 持续时间
    public DelayTask(Duration duration, D date) {
        this.deadLineNanos = System.nanoTime() + duration.toNanos();//加给的时间，达到延时的效果
        this.date = date;
    }

     public static <D> DelayTask<D> of(Duration duration, D date){
      return   new DelayTask(duration, date);
     }

    /**
     * 1.用来获取队列中每个任务，距离当前时间还有多久被执行
     * @param unit the time unit
     * @return
     */
    @Override
    public long getDelay(TimeUnit unit) {
        //输入的时间减系统当前时间，如果结果小于0，则说明任务已经到期，-1是已经过期了
        return unit.convert(Math.max(deadLineNanos - System.nanoTime(),0), TimeUnit.NANOSECONDS)  ;
    }

    /**
     *2.对延时队列中的任务 进行排序（排序依据，根据 getDelay方法获取任务延时时间进行排序，值越小，越先执行）
     * @param o the object to be compared.
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
        //获取两个任务剩余时间，谁小谁先执行
        long diff = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
        return diff > 0 ? 1 : diff == 0 ? 0 : -1 ;
    }
}
